package com.elitesland.org.service.impl;

import com.elitesland.org.convert.OrgAddressBookConvert;
import com.elitesland.org.repo.OrgAddressBookRepo;
import com.elitesland.org.service.OrgAddressBookService;
import com.elitesland.org.vo.OrgAddressBookVO;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

@Service
public class OrgAddressBookServiceImpl implements OrgAddressBookService {

    private OrgAddressBookRepo orgAddressBookRepo;

    @Autowired
    public void setOrgAddressBookRepo(OrgAddressBookRepo orgAddressBookRepo) {
        this.orgAddressBookRepo = orgAddressBookRepo;
    }

    @Override
    public List<OrgAddressBookVO> listById(Long id, String type) {
        return orgAddressBookRepo.findAllByRecordIdAndAddressType(id, type)
                .stream().map(OrgAddressBookConvert.INSTANCE::doToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<OrgAddressBookVO> listByIds(List<Long> ids) {
        return orgAddressBookRepo.findAllByIdIn(ids).stream().map(OrgAddressBookConvert.INSTANCE::doToVO)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackOn = {Exception.class})
    public void createBankInfoInBatch(List<OrgAddressBookVO> abs) {
        AtomicLong primaryId = new AtomicLong(0L);
        abs.forEach(ab -> {
            ab.setAddressType("BA");
            if (ab.getIsPrimary()) {
                primaryId.set(ab.getId());
            }
        });
        orgAddressBookRepo.saveAll(abs.stream().map(OrgAddressBookConvert.INSTANCE::voToDO)
                .collect(Collectors.toList()));
        if (primaryId.get() > 0L) {
            setPrimary(primaryId.get());
        }
    }

    @Override
    @Transactional(rollbackOn = {Exception.class})
    public void createInBatch(List<OrgAddressBookVO> abs) {
        orgAddressBookRepo.saveAll(abs.stream().map(OrgAddressBookConvert.INSTANCE::voToDO)
                .collect(Collectors.toList()));

        AtomicLong primaryId = new AtomicLong(0L);
        abs.forEach(ab -> {
            if (ab.getIsPrimary()) {
                primaryId.set(ab.getId());
            }
        });
        if (primaryId.get() > 0L) {
            setPrimary(primaryId.get());
        }
    }

    @Override
    @Transactional(rollbackOn = {Exception.class})
    public void updateInBatch(List<OrgAddressBookVO> abs) {
        orgAddressBookRepo.saveAll(abs.stream().map(OrgAddressBookConvert.INSTANCE::voToDO)
                .collect(Collectors.toList()));

        AtomicLong primaryId = new AtomicLong(0L);
        abs.forEach(ab -> {
            if (ab.getIsPrimary()) {
                primaryId.set(ab.getId());
            }
        });
        if (primaryId.get() > 0L) {
            setPrimary(primaryId.get());
        }
    }

    @Override
    @Transactional(rollbackOn = {Exception.class})
    public void removeInBatch(List<Long> ids) {
        orgAddressBookRepo.deleteAllByIdIn(ids);
    }

    @Override
    @Transactional(rollbackOn = {Exception.class})
    public void setPrimary(Long id) {
        orgAddressBookRepo.findById(id).ifPresent(ab -> {
            val abs = orgAddressBookRepo.findAllByRecordIdAndAddressType(ab.getRecordId(), ab.getAddressType());
            abs.forEach(a -> {
                if (a.getId().equals(id)) {
                    a.setIsPrimary(true);
                } else {
                    a.setIsPrimary(false);
                }
            });
            orgAddressBookRepo.saveAll(abs);
        });
    }
}
